package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.UserReceviveSound;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.domain.vo.UserLikeVo;
import com.tanhua.dubbo.api.*;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;

@Slf4j
@Service
public class UserService {

    @Reference
    private UserApi userApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Reference
    private LikeApi api;

    @Reference
    private FriendApi friendApi;

    @Reference
    private UserReceviveSoundApi receviveSoundApi;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private IMService service;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    // 定义redis中存储的验证码的key的前缀
    private final String SMS_KEY = "SMS_KEY_";

    // 定义redis中存储的token的key的前缀
    private final String TOKEN_KEY = "TOKEN_KEY_";

    @Value("{tanhua.secret}")
    private String secret;

    //通过手机号寻找
    public ResponseEntity<Object> findByMobile(String mobile) {
        User user = userApi.findByMobile(mobile);
        return ResponseEntity.ok(user);
    }


    //新增用户业务
    public ResponseEntity<Object> save(User user) {
        try {
            Long userID = userApi.save(user);
            receviveSoundApi.save(user.getId());
            return ResponseEntity.ok(userID);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 异常返回：需要返回错误编码、错误信息
        Map<String, Object> resultMap = new HashMap<>();

        // 设置错误信息
        resultMap.put("errorCode", 1000);
        resultMap.put("errMessage", "服务器正在维护，请稍后再试");

        return ResponseEntity.status(500).body(resultMap);
    }

    //login短信发送业务
    public ResponseEntity<Object> SendAuthCode(String phone) {
//        String authCode = RandomStringUtils.randomNumeric(6);
//        smsTemplate.sendSms(phone, authCode);
        String authCode = "123456";

        log.info(SMS_KEY + authCode);
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        ops.set(SMS_KEY + phone, authCode, Duration.ofMinutes(3));
        return ResponseEntity.ok(null);
    }

    //验证码校验业务
    public ResponseEntity<Object> loginVerification(Map<String, String> params) {

        String phone = params.get("phone");
        String code = params.get("verificationCode");
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String origin_code = ops.get(SMS_KEY + phone);

        if (origin_code == null || !code.equals(origin_code)) {
            return ResponseEntity.status(401).body(ErrorResult.loginError());
        }

        //【记录日志-操作类型默认为0101登陆】 --------------------------------------
        String type = "0101";

        boolean isNew = false;
        User user = userApi.findByMobile(phone);

        if (user == null) {
            user = new User();
            user.setMobile(phone);
            Long userId = userApi.save(user);
            user.setId(userId);
            isNew = true;

            //【操作类型为注册 0102】
            type = "0102";
            huanXinTemplate.register(user.getId());
        }

        //【准备日志数据】
        Map<String, Object> map = new HashMap<>();
        map.put("userId", user.getId());
        map.put("type",type );
        map.put("date",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

        //【发送mq消息】-----------------最好使用try-catch异常处理，如果发送失败，记录到数据库
        try {
            rocketMQTemplate.convertAndSend("tanhua-log",JSON.toJSONString(map));
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        String token = JwtUtils.createToken(user.getId(), phone, secret);
        String tokenData = JSON.toJSONString(user);
        ops.set(TOKEN_KEY + token, tokenData, Duration.ofHours(26));

        redisTemplate.delete(SMS_KEY + phone);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("isNew", isNew);
        resultMap.put("token", token);
        return ResponseEntity.ok(resultMap);
    }

    //用户第一次登陆，需要完善用户信息
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo, String token) {
        //根据token,获取用户
        User userByToken = findUserInfoByToken(token);
        if (userByToken == null) {
            //认证失败
            log.info("验证失败");
            return ResponseEntity.status(401).body(ErrorResult.error());
        }
        //设置用户详情id
        userInfo.setId(userByToken.getId());
        //保存
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    //按token在redis中查找User
    public User findUserInfoByToken(String token) {
        //根据token，获取用户信息（json）
        String userJsonString = redisTemplate.opsForValue().get(TOKEN_KEY + token);
        if (StringUtils.isEmpty(userJsonString)) {
            return null;
        }
        //把json字符串转换为对象
        User user = JSON.parseObject(userJsonString, User.class);
        //更新token有效时间
        redisTemplate.opsForValue().set(TOKEN_KEY + token, userJsonString, Duration.ofHours(26));
        return user;
    }

    //获取头像照片业务
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto, String token) throws IOException {
        User user = findUserInfoByToken(token);
        if (user == null) {
            log.info("认证失败");
            return ResponseEntity.status(401).body(ErrorResult.error());
        }

        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(url);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    //根据id查询用户信息业务
    public ResponseEntity<Object> findUserInfoById(Long userID, Long huanxinID) throws InvocationTargetException, IllegalAccessException {

        //1. 根据token获取用户
        Long userId = UserHolder.getUserId();

        //2. 如果userID不为NULL，根据用户id查询
        if (userID != null) {
            userId = userID;
        }else if(huanxinID != null){
            userId = huanxinID;
        }

        //根据用户id查询用户详情
        UserInfo userInfo = userInfoApi.findById(userId);

        //创建封装返回结果的UserInfoVo对象
        UserInfoVo userInfoVo = new UserInfoVo();
        //对象拷贝，参数1为源对象，参数2为目标对象
        BeanUtils.copyProperties(userInfoVo, userInfo);
        if (userInfo.getAge() != null) {
            userInfoVo.setAge(userInfo.getAge().toString());
        }
        return ResponseEntity.ok(userInfoVo);
    }

    //更新用户详细业务
    public ResponseEntity<Object> updateUserInfo(String token, UserInfo userInfo) {
        //根据token获取用户
        User user = findUserInfoByToken(token);
        if (user == null) {
            //认证失败
            log.info("认证失败");
            return ResponseEntity.status(200).body(ErrorResult.error());
        }
        userInfo.setId(user.getId());

        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);

    }

    //更新用户手机号业务
    public ResponseEntity<Object> updateMobile(User user){
        userApi.updateMobile(user);
        return ResponseEntity.ok(null);
    }

    //互相喜欢、粉丝-计数业务
    public ResponseEntity<Object> counts() {
        Long userId = UserHolder.getUserId();

        Long fans = api.countFans(userId);
        Long love = api.countLove(userId);
        Long loveForEach = api.countBoth(userId);

        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("eachLoveCount", loveForEach.intValue());
        map.put("loveCount", love.intValue());
        map.put("fanCount", fans.intValue());

        return ResponseEntity.ok(map);
    }

    //互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表业务
    public ResponseEntity<Object> getTypeQuery(Integer type, Integer page, Integer pagesize, String nickname) throws InvocationTargetException, IllegalAccessException {
        PageResult pageResult = new PageResult();
        Long userId = UserHolder.getUserId();
        switch (type){
            case 1:
                pageResult = api.queryLikeBothByPage(userId,page,pagesize);
                break;
            case 2:
                pageResult = api.queryLoveByPage(page,pagesize,userId);
                break;
            case 3:
                pageResult = api.queryFansByPage(userId,page,pagesize);
                break;
            case 4:
                pageResult = api.queryVisitorByPage(userId,page,pagesize);
                break;
        }
        ArrayList<UserLikeVo> volist = new ArrayList<>();
        List<Map<String,Object>> list = (List<Map<String, Object>>) pageResult.getItems();
        if(list != null){
            for (Map<String, Object> map : list) {
                Long uid = (Long) map.get("userId");
                Long score = (Long) map.get("score");

                UserLikeVo vo = new UserLikeVo();

                UserInfo userInfo = userInfoApi.findById(uid);
                if(userInfo != null){
                    BeanUtils.copyProperties(vo,userInfo);
                }

                vo.setMatchRate(score.intValue());

                volist.add(vo);
            }
        }

        pageResult.setItems(volist);
        return ResponseEntity.ok(pageResult);

    }

    //粉丝 - 喜欢业务
    public ResponseEntity<Object> commitLove(Integer fansId) {
        //移除粉丝数据
        api.remove(UserHolder.getUserId(),fansId);
        //互相关注
        service.addContacts(fansId);
        return ResponseEntity.ok(null);
    }

    //喜欢 - 取消业务
    public ResponseEntity<Object> deleteLike(Integer friendId) {
        Integer remove = friendApi.remove(UserHolder.getUserId(), friendId);

        if (remove==2) {
            api.save(friendId,UserHolder.getUserId());
        }

        return ResponseEntity.ok(null);
    }
}
